home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / src / syscalls.cc < prev    next >
C/C++ Source or Header  |  1997-05-27  |  25KB  |  1,187 lines

  1. /*
  2.  
  3. Copyright (C) 1996 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. // Thomas Baier <baier@ci.tuwien.ac.at> added the original versions of
  24. // the following functions:
  25. //
  26. //   mkfifo  unlink  waitpid
  27.  
  28. /* Modified by Klaus Gebhardt, 1996 */
  29.  
  30. #ifdef HAVE_CONFIG_H
  31. #include <config.h>
  32. #endif
  33.  
  34. #include <cerrno>
  35. #include <cstdio>
  36. #include <cstring>
  37. #include <csignal>
  38.  
  39. #ifdef HAVE_UNISTD_H
  40. #ifdef HAVE_SYS_TYPES_H
  41. #include <sys/types.h>
  42. #endif
  43. #include <unistd.h>
  44. #endif
  45.  
  46. #ifdef HAVE_FCNTL_H
  47. #include <fcntl.h>
  48. #endif
  49.  
  50. #include <process.h>
  51.  
  52. #include "defun.h"
  53. #include "error.h"
  54. #include "file-ops.h"
  55. #include "gripes.h"
  56. #include "help.h"
  57. #include "lo-utils.h"
  58. #include "oct-map.h"
  59. #include "oct-obj.h"
  60. #include "oct-stdstrm.h"
  61. #include "oct-stream.h"
  62. #include "oct-fstrm.h"
  63. #include "sighandlers.h"
  64. #include "sysdep.h"
  65. #include "syswait.h"
  66. #include "utils.h"
  67. #include "variables.h"
  68.  
  69. static Octave_map
  70. mk_stat_map (const file_stat& fs)
  71. {
  72.   Octave_map m;
  73.  
  74.   m["dev"] = (double) fs.dev ();
  75.   m["ino"] = (double) fs.ino ();
  76.   m["modestr"] = fs.mode_as_string ();
  77.   m["nlink"] = (double) fs.nlink ();
  78.   m["uid"] = (double) fs.uid ();
  79.   m["gid"] = (double) fs.gid ();
  80. #if defined (HAVE_ST_RDEV)
  81.   m["rdev"] = (double) fs.rdev ();
  82. #endif
  83.   m["size"] = (double) fs.size ();
  84.   m["atime"] = (double) fs.atime ();
  85.   m["mtime"] = (double) fs.mtime ();
  86.   m["ctime"] = (double) fs.ctime ();
  87. #if defined (HAVE_ST_BLKSIZE)
  88.   m["blksize"] = (double) fs.blksize ();
  89. #endif
  90. #if defined (HAVE_ST_BLOCKS)
  91.   m["blocks"] = (double) fs.blocks ();
  92. #endif
  93.  
  94.   return m;
  95. }
  96.  
  97. DEFUN (_dup, args, ,
  98.  "[FID, MSG] = _dup (old): duplicate a file descriptor")
  99. {
  100.   octave_value_list retval;
  101.  
  102.   retval(1) = string ();
  103.   retval(0) = -1.0;
  104.  
  105.   int nargin = args.length ();
  106.  
  107.   if (nargin == 1)
  108.     {
  109. #if defined (HAVE_DUP)
  110.       double d_old = args(0).double_value ();
  111.  
  112.       if (! error_state)
  113.     {
  114.       if (D_NINT (d_old) == d_old)
  115.         {
  116.           int i_old = NINT (d_old);
  117.  
  118.           // XXX FIXME XXX -- are these checks sufficient?
  119.           if (i_old >= 0)
  120.         {
  121.           int status = dup (i_old);
  122.  
  123.           retval(0) = (double) status;
  124.  
  125.           if (status < 0)
  126.             retval(1) = strerror (errno);
  127.         }
  128.           else
  129.         error ("_dup: invalid file id");
  130.         }
  131.       else
  132.         error ("_dup: argument must be integer value");
  133.     }
  134. #else
  135.       gripe_not_supported ("_dup");
  136. #endif
  137.     }
  138.   else
  139.     print_usage ("_dup");
  140.  
  141.   return retval;
  142. }
  143.  
  144. DEFUN (_dup2, args, ,
  145.  "[FID, MSG] = _dup2 (OLD, NEW)\n\
  146. \n\
  147. Duplicate a file descriptor.\n\
  148. \n\
  149. If successful, FID is greater than zero and contains the new file ID.\n\
  150. Otherwise, FID is negative and MSG contains a system-dependent error message.")
  151. {
  152.   octave_value_list retval;
  153.  
  154.   retval(1) = string ();
  155.   retval(0) = -1.0;
  156.  
  157.   int nargin = args.length ();
  158.  
  159.   if (nargin == 2)
  160.     {
  161. #if defined (HAVE_DUP2)
  162.       double d_old = args(0).double_value ();
  163.       double d_new = args(1).double_value ();
  164.  
  165.       if (! error_state)
  166.     {
  167.       if (D_NINT (d_old) == d_old && D_NINT (d_new) == d_new)
  168.         {
  169.           int i_old = NINT (d_old);
  170.           int i_new = NINT (d_new);
  171.  
  172.           // XXX FIXME XXX -- are these checks sufficient?
  173.           if (i_old >= 0 && i_new >= 0)
  174.         {
  175.           int status = dup2 (i_old, i_new);
  176.  
  177.           retval(0) = (double) status;
  178.  
  179.           if (status < 0)
  180.             retval(1) = strerror (errno);
  181.         }
  182.           else
  183.         error ("_dup2: invalid file id");
  184.         }
  185.       else
  186.         error ("_dup2: arguments must be integer values");
  187.     }
  188. #else
  189.       gripe_not_supported ("_dup2");
  190. #endif
  191.     }
  192.   else
  193.     print_usage ("_dup2");
  194.  
  195.   return retval;
  196. }
  197.  
  198. DEFUN (_close, args, ,
  199.  "[RETVAL, MSG] = _close (fid): close a file handle")
  200. {
  201.   octave_value_list retval;
  202.  
  203.   retval(1) = string ();
  204.   retval(0) = -1.0;
  205.  
  206.   int nargin = args.length ();
  207.  
  208.   if (nargin == 1)
  209.     {
  210.       double d_old = args(0).double_value ();
  211.  
  212.       if (! error_state)
  213.     {
  214.       if (D_NINT (d_old) == d_old)
  215.         {
  216.           int i_old = NINT (d_old);
  217.  
  218.           // XXX FIXME XXX -- are these checks sufficient?
  219.           if (i_old >= 0)
  220.         {
  221.           int status = close (i_old);
  222.  
  223.           retval(0) = (double) status;
  224.  
  225.           if (status < 0)
  226.             retval(1) = strerror (errno);
  227.         }
  228.           else
  229.         error ("_close: invalid file id");
  230.         }
  231.       else
  232.         error ("_close: argument must be integer value");
  233.     }
  234.     }
  235.   else
  236.     print_usage ("_close");
  237.  
  238.   return retval;
  239. }
  240.  
  241. DEFUN (_fdopen, args, ,
  242.  "[FID, MSG] = _fdopen (fid, mode): create a stream for file handle")
  243. {
  244.   octave_value_list retval;
  245.  
  246.   retval(1) = string ();
  247.   retval(0) = -1.0;
  248.  
  249.   int nargin = args.length ();
  250.  
  251.   if (nargin == 2)
  252.     {
  253.       if (args(1).is_string ())
  254.     {
  255.       string mode = args(1).string_value ();
  256.  
  257.       double d_old = args(0).double_value ();
  258.  
  259.       if (! error_state)
  260.         {
  261.           if (D_NINT (d_old) == d_old)
  262.         {
  263.           int i_old = NINT (d_old);
  264.  
  265.           // XXX FIXME XXX -- are these checks sufficient?
  266.           if (i_old >= 0)
  267.             {
  268.               if (mode == "r")
  269.             {
  270.               FILE *f = fdopen (i_old, "r");
  271.               octave_istdiostream *is
  272.                 = new octave_istdiostream ("fdopen", f);
  273.               retval(0) = octave_stream_list::insert (is);
  274.             }
  275.               else if (mode == "w")
  276.             {
  277.               FILE *f = fdopen (i_old, "w");
  278.               octave_ostdiostream *os
  279.                 = new octave_ostdiostream ("fdopen", f);
  280.               retval(0) = octave_stream_list::insert (os);
  281.             }
  282.               else
  283.             error ("_fdopen: invalid mode");
  284.             }
  285.           else
  286.             error ("_fdopen: invalid file id");
  287.         }
  288.           else
  289.         error ("_fdopen: argument must be integer value");
  290.         }
  291.     }
  292.       else
  293.     error ("_fdopen: mode must be a string");
  294.     }
  295.   else
  296.     print_usage ("_fdopen");
  297.  
  298.   return retval;
  299. }
  300.  
  301. DEFUN (spawn, args, ,
  302.  "[STATUS, MSG] = spawn (mode, file, args): run a program")
  303. {
  304.   octave_value_list retval;
  305.  
  306.   retval(1) = string ();
  307.   retval(0) = -1.0;
  308.  
  309.   int nargin = args.length ();
  310.  
  311.   if (nargin == 2 || nargin == 3)
  312.     {
  313. #if defined (HAVE_SPAWNVP)
  314.       string mode_strg = args(0).string_value ();
  315.       string exec_file = args(1).string_value ();
  316.  
  317.       int mode = P_WAIT;
  318.  
  319.       if (mode_strg == "wait")
  320.     mode = P_WAIT;
  321.       else if (mode_strg == "nowait")
  322.     mode = P_NOWAIT;
  323.       else if (mode_strg == "detach")
  324.     mode = P_DETACH;
  325.       else if (mode_strg == "session")
  326.     mode = P_SESSION;
  327.       else if (mode_strg == "pm")
  328.     mode = P_PM;
  329.       else
  330.     error ("system: invalid mode specified.");
  331.  
  332.       if (! error_state)
  333.     {
  334.       char **exec_args = 0;
  335.  
  336.       if (nargin == 3)
  337.         {
  338.           charMatrix chm = args(2).all_strings ();
  339.  
  340.           if (! error_state)
  341.         {
  342.           int nr = chm.rows ();
  343.           int nc = chm.cols ();
  344.  
  345.           exec_args = new char * [nr+2];
  346.  
  347.           // XXX FIXME XXX -- potential leak?
  348.  
  349.           exec_args[0] = strsave (exec_file.c_str ());
  350.           exec_args[nr+1] = 0;
  351.  
  352.           for (int i = 0; i < nr; i++)
  353.             {
  354.               exec_args[i+1] = new char [nc+1];
  355.  
  356.               for (int j = 0; j < nc; j++)
  357.             exec_args[i+1][j] = chm (i, j);
  358.  
  359.               exec_args[i+1][nc] = '\0';
  360.             }
  361.         }
  362.           else
  363.         error ("spawn: arguments must be strings");
  364.         }
  365.       else
  366.         {
  367.           exec_args = new char * [2];
  368.  
  369.           exec_args[0] = strsave (exec_file.c_str ());
  370.           exec_args[1] = 0;
  371.         }
  372.  
  373.       if (! error_state)
  374.         {
  375.           int status = spawnvp (mode, exec_file.c_str (), exec_args);
  376.  
  377.           retval(0) = (double) status;
  378.  
  379.           if (status < 0)
  380.         retval(1) = strerror (errno);
  381.         }
  382.     }
  383.       else
  384.     error ("spawn: first two arguments must be strings");
  385. #else
  386.       gripe_not_supported ("spawn");
  387. #endif
  388.     }
  389.   else
  390.     print_usage ("spawn");
  391.  
  392.   return retval;
  393. }
  394.  
  395. DEFUN (exec, args, ,
  396.  "[STATUS, MSG] = exec (FILE, ARGS)\n\
  397. \n\
  398. Replace current process with a new process.\n\
  399. \n\
  400. If successful, exec does not return.  If exec does return, status will\n\
  401. be nonzero, and MSG will contain a system-dependent error message.")
  402. {
  403.   octave_value_list retval;
  404.  
  405.   retval(1) = string ();
  406.   retval(0) = -1.0;
  407.  
  408.   int nargin = args.length ();
  409.  
  410.   if (nargin == 1 || nargin == 2)
  411.     {
  412. #if defined (HAVE_EXECVP)
  413.       string exec_file = args(0).string_value ();
  414.  
  415.       if (! error_state)
  416.     {
  417.       char **exec_args = 0;
  418.  
  419.       if (nargin == 2)
  420.         {
  421.           charMatrix chm = args(1).all_strings ();
  422.  
  423.           if (! error_state)
  424.         {
  425.           int nr = chm.rows ();
  426.           int nc = chm.cols ();
  427.  
  428.           exec_args = new char * [nr+2];
  429.  
  430.           // XXX FIXME XXX -- potential leak?
  431.  
  432.           exec_args[0] = strsave (exec_file.c_str ());
  433.           exec_args[nr+1] = 0;
  434.  
  435.           for (int i = 0; i < nr; i++)
  436.             {
  437.               exec_args[i+1] = new char [nc+1];
  438.  
  439.               for (int j = 0; j < nc; j++)
  440.             exec_args[i+1][j] = chm (i, j);
  441.  
  442.               exec_args[i+1][nc] = '\0';
  443.             }
  444.         }
  445.           else
  446.         error ("exec: arguments must be strings");
  447.         }
  448.       else
  449.         {
  450.           exec_args = new char * [2];
  451.  
  452.           exec_args[0] = strsave (exec_file.c_str ());
  453.           exec_args[1] = 0;
  454.         }
  455.  
  456.       if (! error_state)
  457.         {
  458.           int status = execvp (exec_file.c_str (), exec_args);
  459.  
  460.           retval(0) = (double) status;
  461.  
  462.           if (status < 0)
  463.         retval(1) = strerror (errno);
  464.         }
  465.     }
  466.       else
  467.     error ("exec: first argument must be a string");
  468. #else
  469.       gripe_not_supported ("exec");
  470. #endif
  471.     }
  472.   else
  473.     print_usage ("exec");
  474.  
  475.   return retval;
  476. }
  477.  
  478. DEFUN (_fcntl, args, ,
  479.  "[STATUS, MSG] = _fcntl (FID, REQUEST, ARGUMENT)\n\
  480. \n\
  481. Control open file descriptors.\n\
  482. \n\
  483. If successful, STATUS is 0 and MSG is an empty string.  Otherwise,\n\
  484. STATUS is nonzero and MSG contains a system-dependent error message.")
  485. {
  486.   octave_value_list retval;
  487.  
  488.   retval(1) = string ();
  489.   retval(0) = -1.0;
  490.  
  491.   int nargin = args.length ();
  492.  
  493.   if (nargin == 3)
  494.     {
  495. #if defined (HAVE_FCNTL)
  496.       double d_fid = args(0).double_value ();
  497.       double d_req = args(1).double_value ();
  498.       double d_arg = args(2).double_value ();
  499.  
  500.       if (! error_state
  501.       && D_NINT (d_fid) == d_fid
  502.       && D_NINT (d_req) == d_req
  503.       && D_NINT (d_arg) == d_arg)
  504.     {
  505.       int fid = NINT (d_fid);
  506.       int req = NINT (d_req);
  507.       int arg = NINT (d_arg);
  508.  
  509.       // XXX FIXME XXX -- Need better checking here?
  510.       if (fid < 0)
  511.         error ("fcntl: invalid file id");
  512.       else
  513.         {
  514.           int status = fcntl (fid, req, arg);
  515.  
  516.           retval(0) = (double) status;
  517.  
  518.           if (status < 0)
  519.         retval(1) = strerror (errno);
  520.         }
  521.     }
  522.       else
  523.     error ("fcntl: file id must be an integer");
  524. #else
  525.       gripe_not_supported ("fcntl");
  526. #endif
  527.     }
  528.   else
  529.     print_usage ("fcntl");
  530.  
  531.   return retval;
  532. }
  533.  
  534. DEFUN (fork, args, ,
  535.  "[PID, MSG] = fork ()\n\
  536. \n\
  537. Create a copy of the current process.\n\
  538. \n\
  539. If successful, PID is either the process ID and you are in the parent,\n\
  540. or 0, and you are in the child.  If PID is less than zero, an error\n\
  541. has occured, and MSG contains a system-dependent error message.")
  542. {
  543.   octave_value_list retval;
  544.  
  545.   retval(1) = string ();
  546.   retval(0) = -1.0;
  547.  
  548.   int nargin = args.length ();
  549.  
  550.   if (nargin == 0)
  551.     {
  552. #if defined (HAVE_FORK)
  553.       pid_t pid = fork ();
  554.  
  555.       retval(0) = (double) pid;
  556.  
  557.       if (pid < 0)
  558.     retval(1) = strerror (errno);
  559. #else
  560.       gripe_not_supported ("fork");
  561. #endif
  562.     }
  563.   else
  564.     print_usage ("fork");
  565.  
  566.   return retval;
  567. }
  568.  
  569. DEFUN (getpgrp, args, ,
  570.   "pgid = getpgrp (): return the process group id of the current process")
  571. {
  572.   double retval = -1.0;
  573.  
  574.   int nargin = args.length ();
  575.  
  576.   if (nargin == 0)
  577.     {
  578. #if defined (HAVE_GETPGRP)
  579.       retval = getpgrp ();
  580. #else
  581.       gripe_not_supported ("getpgrp");
  582. #endif
  583.     }
  584.   else
  585.     print_usage ("getpgrp");
  586.  
  587.   return retval;
  588. }
  589.  
  590. DEFUN (getpid, args, ,
  591.   "pid = getpid (): return the process id of the current process")
  592. {
  593.   double retval = -1.0;
  594.  
  595.   int nargin = args.length ();
  596.  
  597.   if (nargin == 0)
  598.     {
  599. #if defined (HAVE_GETPID)
  600.       retval = getpid ();
  601. #else
  602.       gripe_not_supported ("getpid");
  603. #endif
  604.     }
  605.   else
  606.     print_usage ("getpid");
  607.  
  608.   return retval;
  609. }
  610.  
  611. DEFUN (getppid, args, ,
  612.   "pid = getppid (): return the process id of the parent process")
  613. {
  614.   double retval = -1.0;
  615.  
  616.   int nargin = args.length ();
  617.  
  618.   if (nargin == 0)
  619.     {
  620. #if defined (HAVE_GETPPID)
  621.       retval = getppid ();
  622. #else
  623.       gripe_not_supported ("getppid");
  624. #endif
  625.     }
  626.   else
  627.     print_usage ("getppid");
  628.  
  629.   return retval;
  630. }
  631.  
  632. DEFUN (getegid, args, ,
  633.   "gid = getegid (): return the effective group id of the current process")
  634. {
  635.   double retval = -1.0;
  636.  
  637.   int nargin = args.length ();
  638.  
  639.   if (nargin == 0)
  640.     {
  641. #if defined (HAVE_GETEGID)
  642.       retval = getegid ();
  643. #else
  644.       gripe_not_supported ("getegid");
  645. #endif
  646.     }
  647.   else
  648.     print_usage ("getegid");
  649.  
  650.   return retval;
  651. }
  652.  
  653. DEFUN (getgid, args, ,
  654.   "gid = getgid (): return the real group id of the current process")
  655. {
  656.   double retval = -1.0;
  657.  
  658.   int nargin = args.length ();
  659.  
  660.   if (nargin == 0)
  661.     {
  662. #if defined (HAVE_GETGID)
  663.       retval = getgid ();
  664. #else
  665.       gripe_not_supported ("getgid");
  666. #endif
  667.     }
  668.   else
  669.     print_usage ("getgid");
  670.  
  671.   return retval;
  672. }
  673.  
  674. DEFUN (geteuid, args, ,
  675.   "uid = geteuid (): return the effective user id of the current process")
  676. {
  677.   double retval = -1.0;
  678.  
  679.   int nargin = args.length ();
  680.  
  681.   if (nargin == 0)
  682.     {
  683. #if defined (HAVE_GETEUID)
  684.       retval = geteuid ();
  685. #else
  686.       gripe_not_supported ("geteuid");
  687. #endif
  688.     }
  689.   else
  690.     print_usage ("geteuid");
  691.  
  692.   return retval;
  693. }
  694.  
  695. DEFUN (getuid, args, ,
  696.   "uid = getuid (): return the real user id of the current process")
  697. {
  698.   double retval = -1.0;
  699.  
  700.   int nargin = args.length ();
  701.  
  702.   if (nargin == 0)
  703.     {
  704. #if defined (HAVE_GETUID)
  705.       retval = getuid ();
  706. #else
  707.       gripe_not_supported ("getuid");
  708. #endif
  709.     }
  710.   else
  711.     print_usage ("getuid");
  712.  
  713.   return retval;
  714. }
  715.  
  716. DEFUN (lstat, args, ,
  717.   "[S, ERR, MSG] = lstat (NAME)\n\
  718. \n\
  719. Like [S, ERR, MSG] = stat (NAME), but if NAME refers to a symbolic\n\
  720. link, returns information about the link itself, not the file that it\n\
  721. points to.")
  722. {
  723.   octave_value_list retval;
  724.  
  725.   if (args.length () == 1)
  726.     {
  727.       string fname = oct_tilde_expand (args(0).string_value ());
  728.  
  729.       if (! error_state)
  730.     {
  731.       file_stat fs (fname, false);
  732.  
  733.       if (fs)
  734.         {
  735.           retval(2) = string ();
  736.           retval(1) = 0.0;
  737.           retval(0) = octave_value (mk_stat_map (fs));
  738.         }
  739.       else
  740.         {
  741.           retval(2) = fs.error ();
  742.           retval(1) = -1.0;
  743.           retval(0) = Matrix ();
  744.         }
  745.     }
  746.     }
  747.   else
  748.     print_usage ("lstat");
  749.  
  750.   return retval;
  751. }
  752.  
  753. DEFUN (mkfifo, args, ,
  754.   "[STATUS, MSG] = mkfifo (NAME, MODE)\n\
  755. \n\
  756. Create a FIFO special file named NAME with file mode MODE\n\
  757. \n\
  758. If successful, STATUS is 0 and MSG is an empty string.  Otherwise,\n\
  759. STATUS is nonzero and MSG contains a system-dependent error message.")
  760. {
  761.   octave_value_list retval;
  762.  
  763.   retval(1) = string ();
  764.   retval(0) = -1.0;
  765.  
  766.   int nargin = args.length ();
  767.  
  768.   if (nargin == 2)
  769.     {
  770. #if defined (HAVE_MKFIFO)
  771.       if (args(0).is_string ())
  772.     {
  773.       string name = args(0).string_value ();
  774.  
  775.       if (args(1).is_scalar_type ())
  776.         {
  777.           long mode = (long) args(1).double_value ();
  778.  
  779.           string msg;
  780.  
  781.           int status = oct_mkfifo (name, mode, msg);
  782.  
  783.           retval(0) = (double) status;
  784.  
  785.           if (status < 0)
  786.         retval(1) = msg;
  787.         }
  788.       else
  789.         error ("mkfifo: MODE must be an integer");
  790.     }
  791.       else
  792.     error ("mkfifo: file name must be a string");
  793. #else
  794.       gripe_not_supported ("mkfifo");
  795. #endif
  796.     }
  797.   else
  798.     print_usage ("mkfifo");
  799.  
  800.   return retval;
  801. }
  802.  
  803. DEFUN (_pipe, args, ,
  804.   "[FIDS, STATUS, MSG] = _pipe (): create an interprocess channel.\n\
  805. \n\
  806. Return the FIDS corresponding to the reading and writing ends of\n\
  807. the pipe, as a vector.\n\
  808. \n\
  809. You must open the FIDS using _fdopen!\n\
  810. \n\
  811. If successful, STATUS is 0 and MSG is an empty string.  Otherwise,\n\
  812. STATUS is nonzero and MSG contains a system-dependent error message.")
  813. {
  814.   octave_value_list retval;
  815.  
  816.   retval(2) = string ();
  817.   retval(1) = -1.0;
  818.   retval(0) = Matrix ();
  819.  
  820.   int nargin = args.length ();
  821.  
  822.   if (nargin == 0)
  823.     {
  824. #if defined (HAVE_PIPE)
  825.       int fid[2];
  826.  
  827.       int status = pipe (fid);
  828.  
  829.       if (status < 0)  retval(2) = strerror (errno);
  830.       else
  831.     {
  832.       Matrix file_ids (1, 2);
  833.  
  834.       file_ids (0, 0) = (double) fid[0];
  835.       file_ids (0, 1) = (double) fid[1];
  836.  
  837.           retval(0) = file_ids;
  838.       retval(1) = (double) status;
  839.     }      
  840. #else
  841.       gripe_not_supported ("_pipe");
  842. #endif
  843.     }
  844.   else
  845.     print_usage ("_pipe");
  846.  
  847.   return retval;
  848. }
  849.  
  850. DEFUN (pipe, args, ,
  851.   "[FILE_IDS, STATUS, MSG] = pipe (): create an interprocess channel.\n\
  852. \n\
  853. Return the FILE_IDS corresponding to the reading and writing ends of\n\
  854. the pipe, as a vector.\n\
  855. \n\
  856. If successful, STATUS is 0 and MSG is an empty string.  Otherwise,\n\
  857. STATUS is nonzero and MSG contains a system-dependent error message.")
  858. {
  859.   octave_value_list retval;
  860.  
  861.   retval(2) = string ();
  862.   retval(1) = -1.0;
  863.   retval(0) = Matrix ();
  864.  
  865.   int nargin = args.length ();
  866.  
  867.   if (nargin == 0)
  868.     {
  869. #if defined (HAVE_PIPE)
  870.       int fid[2];
  871.  
  872.       int status = pipe (fid);
  873.  
  874.       if (status < 0)
  875.     {
  876.       retval(2) = strerror (errno);
  877.     }
  878.       else
  879.     {
  880.       FILE *in_file = fdopen (fid[0], "r");
  881.       FILE *out_file = fdopen (fid[1], "w");
  882.  
  883.       octave_istdiostream *is
  884.         = new octave_istdiostream (string (), in_file);
  885.  
  886.       octave_ostdiostream *os
  887.         = new octave_ostdiostream (string (), out_file);
  888.  
  889.       Matrix file_ids (1, 2);
  890.  
  891.       file_ids (0, 0) = octave_stream_list::insert (is);
  892.       file_ids (0, 1) = octave_stream_list::insert (os);
  893.  
  894.           retval(0) = file_ids;
  895.       retval(1) = (double) status;
  896.     }      
  897. #else
  898.       gripe_not_supported ("pipe");
  899. #endif
  900.     }
  901.   else
  902.     print_usage ("pipe");
  903.  
  904.   return retval;
  905. }
  906.  
  907. DEFUN (stat, args, ,
  908.   "[S, ERR, MSG] = stat (NAME)\n\
  909. \n\
  910.   Given the name of a file, return a structure S with the following\n\
  911.   elements:\n\
  912. \n\
  913.     dev     : id of device containing a directory entry for this file\n\
  914.     ino     : file number of the file\n\
  915.     modestr : file mode, as a string of ten letters or dashes as in ls -l\n\
  916.     nlink   : number of links\n\
  917.     uid     : user id of file's owner\n\
  918.     gid     : group id of file's group\n\
  919.     rdev    : id of device for block or character special files\n\
  920.     size    : size in bytes\n\
  921.     atime   : time of last access\n\
  922.     mtime   : time of last modification\n\
  923.     ctime   : time of last file status change\n\
  924.     blksize : size of blocks in the file\n\
  925.     blocks  : number of blocks allocated for file\n\
  926. \n\
  927.   If the call is successful, ERR is 0 and MSG is an empty string.\n\
  928. \n\
  929.   If the file does not exist, or some other error occurs, S is an\n\
  930.   empty matrix, ERR is -1, and MSG contains the corresponding\n\
  931.   system error message.")
  932. {
  933.   octave_value_list retval;
  934.  
  935.   if (args.length () == 1)
  936.     {
  937.       string fname = oct_tilde_expand (args(0).string_value ());
  938.  
  939.       if (! error_state)
  940.     {
  941.       file_stat fs (fname);
  942.  
  943.       if (fs)
  944.         {
  945.           retval(2) = string ();
  946.           retval(1) = 0.0;
  947.           retval(0) = octave_value (mk_stat_map (fs));
  948.         }
  949.       else
  950.         {
  951.           retval(2) = fs.error ();
  952.           retval(1) = -1.0;
  953.           retval(0) = Matrix ();
  954.         }
  955.     }
  956.     }
  957.   else
  958.     print_usage ("stat");
  959.  
  960.   return retval;
  961. }
  962.  
  963. DEFUN (unlink, args, ,
  964.   "[STATUS, MSG] = unlink (NAME)\n\
  965. \n\
  966. Delete the file NAME\n\
  967. \n\
  968. If successful, STATUS is 0 and MSG is an empty string.  Otherwise,\n\
  969. STATUS is nonzero and MSG contains a system-dependent error message.")
  970. {
  971.   octave_value_list retval;
  972.  
  973.   retval(1) = string ();
  974.   retval(0) = -1.0;
  975.  
  976.   int nargin = args.length ();
  977.  
  978.   if (nargin == 1)
  979.     {
  980.       if (args(0).is_string ())
  981.     {
  982.       string name = args(0).string_value ();
  983.  
  984.       string msg;
  985.  
  986.       int status = oct_unlink (name, msg);
  987.  
  988.       retval(0) = (double) status;
  989.  
  990.       if (status < 0)
  991.         retval(1) = msg;        
  992.     }
  993.       else
  994.     error ("unlink: file name must be a string");
  995.     }
  996.   else
  997.     print_usage ("unlink");
  998.  
  999.   return retval;
  1000. }
  1001.  
  1002. DEFUN (waitpid, args, ,
  1003.   "[PID, MSG] = waitpid (PID, OPTIONS)\n\
  1004. \n\
  1005. Wait for process PID to terminate\n\
  1006. \n\
  1007.   PID can be:\n\
  1008. \n\
  1009.      -1 : wait for any child process\n\
  1010.       0 : wait for any child process whose process group ID is equal to\n\
  1011.           that of the Octave interpreter process.\n\
  1012.     > 0 : wait for termination of the child process with ID PID.\n\
  1013. \n\
  1014.   OPTIONS is:\n\
  1015. \n\
  1016.      0 : wait until signal is received or a child process exits (this\n\
  1017.          is the default if the OPTIONS argument is missing)\n\
  1018.      1 : do not hang if status is not immediately available\n\
  1019.      2 : report the status of any child processes that are\n\
  1020.          stopped, and whose status has not yet been reported\n\
  1021.          since they stopped\n\
  1022.      3 : implies both 1 and 2\n\
  1023. \n\
  1024. If successful, PID is greater than 0 and contains the process ID of\n\
  1025. the child process that exited and MSG is an empty string.\n\
  1026. Otherwise, PID is less than zero and MSG contains a system-dependent\n\
  1027. error message.")
  1028. {
  1029.   octave_value_list retval;
  1030.  
  1031.   retval(1) = string ();
  1032.   retval(0) = -1.0;
  1033.  
  1034.   int nargin = args.length ();
  1035.  
  1036.   if (nargin == 1 || nargin == 2)
  1037.     {
  1038. #if defined (HAVE_WAITPID)
  1039.       double pid_num = args(0).double_value ();
  1040.   
  1041.       if (! error_state)
  1042.     {
  1043.       if (D_NINT (pid_num) != pid_num)
  1044.         error ("waitpid: PID must be an integer value");
  1045.       else
  1046.         {
  1047.           pid_t pid = (pid_t) pid_num;
  1048.  
  1049.           int options = 0;
  1050.  
  1051.           if (args.length () == 2)
  1052.         {
  1053.           double options_num = args(1).double_value ();
  1054.  
  1055.           if (! error_state)
  1056.             {
  1057.               if (D_NINT (options_num) != options_num)
  1058.             error ("waitpid: PID must be an integer value");
  1059.               else
  1060.             {
  1061.               options = NINT (options_num);
  1062.               if (options < 0 || options > 3)
  1063.                 error ("waitpid: invalid OPTIONS value specified");
  1064.             }
  1065.             }
  1066.         }
  1067.  
  1068.           if (! error_state)
  1069.         {
  1070. #ifdef __EMX__
  1071.           volatile octave_interrupt_handler saved_interrupt_handler
  1072.             = octave_ignore_interrupts ();
  1073.  
  1074.           volatile sig_handler *saved_sigchld_handler
  1075.             = octave_set_signal_handler (SIGCHLD, SIG_IGN);
  1076. #endif
  1077.           pid_t status = waitpid (pid, 0, options);
  1078. #ifdef __EMX__
  1079.           octave_set_interrupt_handler (saved_interrupt_handler);
  1080.           octave_set_signal_handler (SIGCHLD, saved_sigchld_handler);
  1081. #endif
  1082.           retval(0) = (double) status;
  1083.  
  1084.           if (status < 0)
  1085.             retval(1) = strerror (errno);
  1086.         }
  1087.         }
  1088.     }
  1089. #else
  1090.       gripe_not_supported ("waitpid");
  1091. #endif
  1092.     }
  1093.   else
  1094.     print_usage ("waitpid");
  1095.  
  1096.   return retval;
  1097. }
  1098.  
  1099. #if !defined (O_NONBLOCK) && defined (O_NDELAY)
  1100. #define O_NONBLOCK O_NDELAY
  1101. #endif
  1102.  
  1103. void
  1104. symbols_of_syscalls (void)
  1105. {
  1106. #if defined (F_DUPFD)
  1107.   DEFCONST (F_DUPFD, (double) F_DUPFD, 0, 0,
  1108.     "");
  1109. #endif
  1110.  
  1111. #if defined (F_GETFD)
  1112.   DEFCONST (F_GETFD, (double) F_GETFD, 0, 0,
  1113.     "");
  1114. #endif
  1115.  
  1116. #if defined (F_GETFL)
  1117.   DEFCONST (F_GETFL, (double) F_GETFL, 0, 0,
  1118.     "");
  1119. #endif
  1120.  
  1121. #if defined (F_SETFD)
  1122.   DEFCONST (F_SETFD, (double) F_SETFD, 0, 0,
  1123.     "");
  1124. #endif
  1125.  
  1126. #if defined (F_SETFL)
  1127.   DEFCONST (F_SETFL, (double) F_SETFL, 0, 0,
  1128.     "");
  1129. #endif
  1130.  
  1131. #if defined (O_APPEND)
  1132.   DEFCONST (O_APPEND, (double) O_APPEND, 0, 0,
  1133.     "");
  1134. #endif
  1135.  
  1136. #if defined (O_ASYNC)
  1137.   DEFCONST (O_ASYNC, (double) O_ASYNC, 0, 0,
  1138.     "");
  1139. #endif
  1140.  
  1141. #if defined (O_CREAT)
  1142.   DEFCONST (O_CREAT, (double) O_CREAT, 0, 0,
  1143.     "");
  1144. #endif
  1145.  
  1146. #if defined (O_EXCL)
  1147.   DEFCONST (O_EXCL, (double) O_EXCL, 0, 0,
  1148.     "");
  1149. #endif
  1150.  
  1151. #if defined (O_NONBLOCK)
  1152.   DEFCONST (O_NONBLOCK, (double) O_NONBLOCK, 0, 0,
  1153.     "");
  1154. #endif
  1155.  
  1156. #if defined (O_RDONLY)
  1157.   DEFCONST (O_RDONLY, (double) O_RDONLY, 0, 0,
  1158.     "");
  1159. #endif
  1160.  
  1161. #if defined (O_RDWR)
  1162.   DEFCONST (O_RDWR, (double) O_RDWR, 0, 0,
  1163.     "");
  1164. #endif
  1165.  
  1166. #if defined (O_SYNC)
  1167.   DEFCONST (O_SYNC, (double) O_SYNC, 0, 0,
  1168.     "");
  1169. #endif
  1170.  
  1171. #if defined (O_TRUNC)
  1172.   DEFCONST (O_TRUNC, (double) O_TRUNC, 0, 0,
  1173.     "");
  1174. #endif
  1175.  
  1176. #if defined (O_WRONLY)
  1177.   DEFCONST (O_WRONLY, (double) O_WRONLY, 0, 0,
  1178.     "");
  1179. #endif
  1180. }
  1181.  
  1182. /*
  1183. ;;; Local Variables: ***
  1184. ;;; mode: C++ ***
  1185. ;;; End: ***
  1186. */
  1187.